package com.sam.thread;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * corePoolSize：线程池维护线程最小的数量，默认为1
 * maxPoolSize：线程池维护线程最大数量，默认为Integer.MAX_VALUE
 * keepAliveSeconds：(maxPoolSize-corePoolSize)部分线程空闲最大存活时间，默认存活时间是60s
 * queueCapacity：阻塞任务队列的大小，默认为Integer.MAX_VALUE，默认使用LinkedBlockingQueue, 进入队列的任务只能由corePool执行
 * allowCoreThreadTimeOut：设置为true的话，keepAliveSeconds参数设置的有效时间对corePoolSize线程也有效，默认是flase,允许Core Thread超时后可以关闭.
 * threadFactory：：用于设置创建线程的工厂，可以通过线程工厂给每个创建出来的线程设置更有意义的名字。使用开源框架guava提供的ThreadFactoryBuilder可以快速给线程池里的线程设置有意义的名字
 * rejectedExecutionHandler：拒绝策略，当队列workQueue和线程池maxPoolSize都满了，说明线程池处于饱和状态，那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy，表示无法处理新任务时抛出异常，有以下四种策略，当然也可以根据实际业务需求类实现RejectedExecutionHandler接口实现自己的处理策略
 * ①AbortPolicy：丢弃任务，并且抛出RejectedExecutionException异常
 * ②DiscardPolicy：丢弃任务，不处理，不抛出异常
 * ③CallerRunsPolicy：只用调用者所在线程来运行任务
 * ③DiscardOldestPolicy：丢弃队列里最近的一个任务，并执行当前任务，并且重复该操作
 *
 * 关闭线程池
 * 调用shutdown或者shutdownNow，
 * 两者都不会接受新的任务，而且通过调用要停止线程的interrupt方法来中断线程，有可能线程永远不会被中断，
 * 不同之处在于shutdownNow会首先将线程池的状态设置为STOP，然后尝试停止所有线程（有可能导致部分任务没有执行完）然后返回未执行任务的列表。
 * 而shutdown则只是将线程池的状态设置为shutdown，然后中断所有没有执行
 * 任务的线程，并将剩余的任务执行完。
 *
 * 常用状态：
 * executor.getThreadPoolExecutor().getQueue().size();：线程需要执行的任务个数。
 * getPoolSize：获取当前线程池的线程数量。
 * getActiveCount：获取活动的线程的数量
 *
 * 提交任务-->corePool是否有空闲线程
 *              有-->由corePool中的线程执行
 *              无-->是否可以加入到队列中进行排队
 *                  是-->加入到队列,由corePool中的线程依次执行
 *                  否-->当前线程数是否超过maxPoolSize
 *                      是-->根据（rejectedExecutionHandler）拒绝策略执行
 *                      否-->创建新线程执行任务
 */
@Configuration
public class ThreadPoolUtil {

    private static ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

    @Value("${threadpool.core-pool-size:5}")
    private int corePoolSize;

    @Value("${threadpool.max-pool-size:10}")
    private int maxPoolSize;

    @Value("${threadpool.queue-capacity:10}")
    private int queueCapacity;

    @Value("${threadpool.keep-alive-seconds:20}")
    private int keepAliveSeconds;



    @Bean("threadPool")
    public ThreadPoolTaskExecutor asyncServiceExecutor() {

        //配置核心线程数
        executor.setCorePoolSize(corePoolSize);
        //配置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        // 空闲的多余线程最大存活时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("async-resource-schedule-");

        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
        // CALLER_RUNS：不在新线程中执行任务，而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }

    public void shutdown(){
        executor.shutdown();
    }

}
